package com.jiawa.train.member.service.Impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import com.jiawa.train.common.exception.BusinessException;
import com.jiawa.train.common.exception.BusinessExceptionEnum;
import com.jiawa.train.common.util.JwtUtil;
import com.jiawa.train.common.util.SnowUtil;
import com.jiawa.train.member.domain.Member;
import com.jiawa.train.member.domain.MemberExample;
import com.jiawa.train.member.domain.SendCode;
import com.jiawa.train.member.mapper.MemberMapper;
import com.jiawa.train.member.mapper.SendCodeMapper;
import com.jiawa.train.member.req.MemberLoginReq;
import com.jiawa.train.member.req.MemberRegisterReq;
import com.jiawa.train.member.req.MemberSendCodeReq;
import com.jiawa.train.member.resp.MemberLoginResp;
import com.jiawa.train.member.service.MemberService;
import jakarta.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.sql.Timestamp;
import java.util.List;

/**
 * @author zzl
 * @version 1.0
 */
@Service
public class MemberServiceImpl implements MemberService {

    private static final Logger LOG = LoggerFactory.getLogger(MemberServiceImpl.class);

    @Resource
    private MemberMapper memberMapper;
    @Resource
    private SendCodeMapper sendCodeMapper;

    @Override
    public Integer count() {
        return Integer.valueOf(Math.toIntExact(memberMapper.countByExample(null)));
    }

    /**
     * 测试注册功能
     * @param req
     * @return
     */
    @Override
    public long register(MemberRegisterReq req) {
        String mobile = req.getMobile();
        Member memberDB = selectByMobile(mobile);

        if(ObjectUtil.isNotNull(memberDB)) {
            throw new BusinessException(BusinessExceptionEnum.MEMBER_MOBILE_EXIST);
        }
        Member member = new Member();
        member.setId(SnowUtil.getSnowflakeNextId());
        member.setMobile(mobile);
        memberMapper.insert(member);
        return member.getId();
    }

    /**
     * 发送短信
     * @param req
     * @return
     */
    @Override
    public String sendCode(MemberSendCodeReq req) {
        String mobile = req.getMobile();
        Member memberDB = selectByMobile(mobile);

        if(ObjectUtil.isNull(memberDB)) {
            LOG.info("手机号不存在，插入一条记录");
            Member member = new Member();
            member.setId(SnowUtil.getSnowflakeNextId());
            member.setMobile(mobile);
            memberMapper.insert(member);
        } else {
            LOG.info("手机号存在，不插入记录");
        }

        SendCode sendCode = sendCodeMapper.getSendCode(mobile);
        if(ObjectUtil.isNotNull(sendCode)) {
            Timestamp now = new Timestamp(System.currentTimeMillis());
            LOG.info("当前时间：" + now);
            if(sendCode.getStartTime().before(now) && sendCode.getEndTime().after(now) && sendCode.getStatus() == 0) {
                throw new BusinessException(BusinessExceptionEnum.MEMBER_MOBILE_CODE_SEND);
            }

            // 生成验证码
            String code = RandomUtil.randomString(4);
            LOG.info("生成短信验证码：{}", code);

            // 保存短信记录表：手机号，短信验证码，有效期，是否已使用，业务类型，发送时间，使用时间
            LOG.info("保存短信记录表");
            long startTime = System.currentTimeMillis();
            long endTime = startTime + 5 * 60 * 1000l;
            sendCodeMapper.deleteSendCode(mobile);
            sendCodeMapper.sendCode(mobile, code, new Timestamp(startTime), new Timestamp(endTime));

            //        TODO:对接短信
            // 对接短信通道，发送短信
            LOG.info("对接短信通道");
            return code;
        } else {

            // 生成验证码
            String code = RandomUtil.randomString(4);
//        String code = "8888";
            LOG.info("生成短信验证码：{}", code);

            // 保存短信记录表：手机号，短信验证码，有效期，是否已使用，业务类型，发送时间，使用时间
            LOG.info("保存短信记录表");
            long startTime = System.currentTimeMillis();
            long endTime = startTime + 5 * 60 * 1000l;
            sendCodeMapper.sendCode(mobile, code, new Timestamp(startTime), new Timestamp(endTime));

            //        TODO:对接短信
            // 对接短信通道，发送短信
            LOG.info("对接短信通道");
            return code;
        }
    }

    /**
     * 注册
     * @param req
     * @return
     */
    @Override
    public MemberLoginResp login(MemberLoginReq req) {
        String mobile = req.getMobile();
        String password = req.getPassword();
        LOG.info("用户密码：{}", mobile);
        LOG.info("用户密码：{}", password);
        Member memberDB = selectByMobile(mobile);
//        TODO:设置布隆过滤器，防止未注册用户直接登录

        if(ObjectUtil.isNull(memberDB)) {
            throw new BusinessException(BusinessExceptionEnum.MEMBER_MOBILE_NOT_EXIST);
        }
        if(!password.equals(memberDB.getPassword())) {
            throw new BusinessException(BusinessExceptionEnum.MEMBER_PASSWORD_ERROR);
        }
        LOG.info("对接短信通道");
//        SendCode sendCode = sendCodeMapper.getSendCode(mobile);
//        Timestamp now = new Timestamp(System.currentTimeMillis());
//        LOG.info("当前时间：" + now);
//        if(sendCode.getStartTime().after(now) || sendCode.getEndTime().before(now)) {
//            throw new BusinessException(BusinessExceptionEnum.MEMBER_MOBILE_CODE_EXPIRE);
//        }
//        TODO:对接短信
        // 校验短信验证码
//        if (!sendCode.getCode().equals(code)) {
//            throw new BusinessException(BusinessExceptionEnum.MEMBER_MOBILE_CODE_ERROR);
//        }
//        if(sendCode.getStatus() == 1) {
//            throw new BusinessException(BusinessExceptionEnum.MEMBER_MOBILE_CODE_USED);
//        }
//        sendCodeMapper.setSendCode(mobile);

        MemberLoginResp memberLoginResp = BeanUtil.copyProperties(memberDB, MemberLoginResp.class);
        String token = JwtUtil.createToken(memberLoginResp.getId(), memberLoginResp.getMobile());
        memberLoginResp.setToken(token);
        return memberLoginResp;
    }

    /**
     * 通过手机号查询会员
     * @param mobile
     * @return
     */
    private Member selectByMobile(String mobile) {
        MemberExample memberExample = new MemberExample();
        memberExample.createCriteria().andMobileEqualTo(mobile);
        List<Member> list = memberMapper.selectByExample(memberExample);
        if(CollUtil.isEmpty(list)) {
            return null;
        } else {
            return list.get(0);
        }
    }
}
